<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>文件管理系统 - 后台</title>
    <!-- Bootstrap CSS -->
    <link th:href="@{/css/bootstrap.css}" rel="stylesheet">
    <!-- Font Awesome -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <!-- Simple DataTables CSS -->
    <link th:href="@{/css/tables.css}" rel="stylesheet">
    <!-- 文件上传组件 CSS -->
    <link rel="shortcut icon" th:href="@{../ico/favicon.ico}"/>
    <!--修改密码css-->
    <style>
        /* 解决两个倒三角的问题 */
        .select2-selection__arrow {
            display: none; /* 隐藏 Bootstrap 的默认箭头 */
        }

        .select2-container {
            position: relative;
        }

        .select2-selection__rendered {
            padding-right: 30px; /* 给右侧留出足够空间显示自定义图标 */
        }

        .select2-selection__arrow:before {
            content: none; /* 去除原生的下拉箭头 */
        }

        /* 如果仍然显示 Font Awesome 图标，可以通过此样式覆盖 */
        select.form-select {
            -webkit-appearance: none;
            -moz-appearance: none;
            appearance: none;
            background-image: none; /* 禁止显示重复的背景图标 */
            padding-right: 35px; /* 增加右边内边距 */
        }


        /* 必填字段星号样式 */
        .text-danger {
            color: #dc3545 !important;
        }

        /* 验证反馈样式 */
        .invalid-feedback {
            display: none;
            width: 100%;
            margin-top: 0.25rem;
            font-size: 0.875em;
            color: #dc3545;
        }

        .was-validated .form-control:invalid,
        .was-validated .form-select:invalid {
            border-color: #dc3545;
        }

        .was-validated .form-control:invalid:focus,
        .was-validated .form-select:invalid:focus {
            border-color: #dc3545;
            box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
        }

        .was-validated .form-control:invalid ~ .invalid-feedback,
        .was-validated .form-select:invalid ~ .invalid-feedback {
            display: block;
        }

        /* 添加以下CSS样式 */
        .toggle-password {
            border-top-left-radius: 0;
            border-bottom-left-radius: 0;
        }

        .toast {
            min-width: 300px;
        }

        /* 密码强度指示器 */
        .password-strength {
            height: 5px;
            margin-top: 5px;
            border-radius: 2px;
            transition: all 0.3s ease;
        }

        .password-strength.weak {
            background-color: #e74c3c;
            width: 33%;
        }

        .password-strength.medium {
            background-color: #f39c12;
            width: 66%;
        }

        .password-strength.strong {
            background-color: #27ae60;
            width: 100%;
        }
    </style>
    <style>
        .upload-area {
            border: 2px dashed #ccc;
            padding: 20px;
            text-align: center;
            margin-bottom: 20px;
        }

        .progress-container {
            margin-top: 20px;
        }

        /* 进度条核心样式 - 确保显示 */
        .progress {
            height: 24px;
            background-color: #f0f0f0;
            border-radius: 10px;
            overflow: hidden;
            /* 确保进度条不会被其他元素覆盖 */
            position: relative;
            z-index: 10;
            /* 确保有足够的边距显示 */
            margin: 10px 0;
            width: 100%;
            display: block !important;
        }

        .progress-bar {
            height: 100%;
            background-color: #4CAF50;
            width: 0%;
            transition: width 0.3s ease;
            display: flex !important;
            align-items: center;
            justify-content: center;
            color: white;
            font-weight: 500;
        }

        .file-info {
            margin-top: 10px;
            font-size: 14px;
        }

        .upload-list {
            margin-top: 20px;
            /* 确保上传列表区域可见 */
            min-height: 50px;
        }

        .upload-item,
        .uploading-item {
            border: 1px solid #ddd;
            padding: 10px;
            margin-bottom: 10px;
            border-radius: 5px;
            /* 确保项目不会被隐藏 */
            display: block !important;
            position: relative;
        }

        /* 基础样式 */
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            overflow-x: hidden;
            color: #333;
            background-color: #f8f9fa;
            padding-top: 20px;
        }

        .container {
            max-width: 1200px;
        }

        .url-link {
            color: #3498db;
            text-decoration: none;
            font-weight: 500;
            display: inline-block;
            max-width: 200px;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            transition: all 0.2s ease;
        }

        .url-link:hover {
            color: #2980b9;
            text-decoration: underline;
        }

        /* 侧边栏样式 */
        .sidebar {
            min-height: 100vh;
            background-color: #2c3e50;
            color: white;
            transition: all 0.3s ease;
            box-shadow: 2px 0 5px rgba(0, 0, 0, 0.1);
        }

        .sidebar .nav-link {
            color: rgba(255, 255, 255, 0.8);
            padding: 0.8rem 1.5rem;
            transition: all 0.3s ease;
            border-left: 3px solid transparent;
            cursor: pointer;
        }

        .sidebar .nav-link:hover {
            color: white;
            background-color: rgba(255, 255, 255, 0.1);
        }

        .sidebar .nav-link.active {
            color: white;
            background-color: #3498db;
            border-left: 3px solid #2980b9;
        }

        .sidebar .nav-link i {
            margin-right: 10px;
            width: 20px;
            text-align: center;
        }

        /* 内容区域样式 */
        .content {
            transition: all 0.3s ease;
            padding: 2rem;
        }

        .page-title {
            margin-bottom: 1.5rem;
            color: #2c3e50;
            font-weight: 600;
            position: relative;
            padding-bottom: 0.5rem;
        }

        .page-title::after {
            content: '';
            position: absolute;
            bottom: 0;
            left: 0;
            width: 50px;
            height: 3px;
            background-color: #3498db;
        }

        /* 卡片样式 */
        .card {
            border: none;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
            transition: transform 0.3s ease, box-shadow 0.3s ease;
            margin-bottom: 30px;
            overflow: visible !important;
        }

        .card:hover {
            transform: translateY(-3px);
            box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1);
        }

        .card-header {
            background-color: white;
            border-bottom: 1px solid #f1f1f1;
            font-weight: 500;
            color: #2c3e50;
        }

        .card-body {
            overflow: visible !important;
        }

        /* 按钮样式 */
        .btn {
            transition: all 0.2s ease;
            border-radius: 4px;
        }

        .btn-primary {
            background-color: #3498db;
            border-color: #3498db;
        }

        .btn-primary:hover {
            background-color: #2980b9;
            border-color: #2980b9;
        }

        .btn-danger {
            background-color: #e74c3c;
            border-color: #e74c3c;
        }

        .btn-danger:hover {
            background-color: #c0392b;
            border-color: #c0392b;
        }

        .btn-action {
            margin: 0 3px;
        }

        /* 表格样式 */
        table.dataTable {
            border-collapse: separate;
            border-spacing: 0;
            width: 100% !important;
        }

        table.dataTable thead th {
            background-color: #f8f9fa;
            border-bottom: 2px solid #e9ecef;
            font-weight: 600;
            color: #495057;
            padding: 12px;
        }

        table.dataTable tbody tr {
            transition: background-color 0.2s ease;
        }

        table.dataTable tbody tr:hover {
            background-color: rgba(52, 152, 219, 0.05);
        }

        /* 页面内容样式 */
        .page-content {
            display: none;
        }

        .page-content.active {
            display: block;
        }

        /* 移动端菜单 */
        .mobile-menu-toggle {
            display: none;
            position: fixed;
            top: 15px;
            left: 15px;
            z-index: 1050;
            background-color: #3498db;
            color: white;
            border: none;
            width: 40px;
            height: 40px;
            border-radius: 50%;
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
        }

        @media (max-width: 768px) {
            .mobile-menu-toggle {
                display: flex;
            }

            .sidebar {
                position: fixed;
                z-index: 1040;
                transform: translateX(-100%);
            }

            .sidebar.show {
                transform: translateX(0);
            }

            .content {
                padding: 1rem;
                margin-left: 0 !important;
            }
        }

        .upload-progress {
            margin-top: 15px;
        }

        .badge {
            font-size: 0.85em;
            padding: 0.35em 0.65em;
        }

        /* 消息提示 */
        .alert {
            margin-bottom: 20px;
            padding: 12px 20px;
            border-radius: 6px;
            border: 1px solid transparent;
        }

        .alert-success {
            background-color: #d1e7dd;
            color: #0f5132;
            border-color: #badbcc;
        }

        .alert-danger {
            background-color: #f8d7da;
            color: #842029;
            border-color: #f5c2c7;
        }

        /* 确保上传列表不会被隐藏 */
        #uploadList {
            display: block !important;
            visibility: visible !important;
            opacity: 1 !important;
            height: auto !important;
            overflow: visible !important;
        }

        /* 上传完成全局弹窗 */
        .global-notification {
            position: fixed;
            top: 20px;
            right: 20px;
            background-color: white;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
            padding: 15px 20px;
            z-index: 10000;
            transform: translateX(120%);
            transition: transform 0.3s ease;
            max-width: 350px;
            border-left: 4px solid #4CAF50;
        }

        .global-notification.show {
            transform: translateX(0);
        }

        .global-notification .title {
            font-weight: 600;
            margin-bottom: 5px;
            color: #333;
        }

        .global-notification .message {
            color: #666;
            font-size: 14px;
        }
    </style>
</head>

<body>
<!-- 上传完成全局弹窗 -->
<div id="globalNotification" class="global-notification">
    <div class="title">上传完成</div>
    <div class="message" id="notificationMessage"></div>
</div>

<!-- 移动端菜单按钮 -->
<button class="mobile-menu-toggle d-flex align-items-center justify-content-center">
    <i class="fas fa-bars"></i>
</button>

<div class="container-fluid p-0">
    <div class="row g-0">
        <!-- 左侧导航栏 -->
        <div class="col-md-3 col-lg-2 sidebar">
            <div class="p-3 mb-4 border-bottom border-light">
                <h4 class="text-white mb-0"><i class="fas fa-cogs me-2"></i>文件管理系统</h4>
            </div>
            <ul class="nav flex-column">
                <li class="nav-item">
                    <a class="nav-link active" href="#" data-page="title-manage-page">
                        <i class="fas fa-file"></i>标题管理
                    </a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#" data-page="file-manage-page">
                        <i class="fas fa-file"></i>文件管理
                    </a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#" data-page="category-page">
                        <i class="fas fa-folder"></i>分类管理
                    </a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#" data-page="upload-page">
                        <i class="fas fa-upload"></i>文件上传
                    </a>
                </li>
            </ul>
        </div>

        <!-- 主内容区域 -->
        <div class="col-md-9 ms-sm-auto col-lg-10 px-md-4 content">
            <div id="title-manage-page" class="page-content active">
                <h2 class="page-title">网站设置</h2>

                <!-- 网站标题设置 -->
                <div class="card">
                    <div class="card-header">
                        <i class="fa fa-heading mr-2"></i>网站标题设置
                    </div>
                    <div class="card-body">
                        <form id="title-form" th:action="@{/admin/modifyTitle}" method="post">
                            <div class="mb-3">
                                <label for="title" class="form-label">网站标题 <span class="text-danger">*</span></label>
                                <input type="text" class="form-control" id="title" name="title"
                                       th:value="${title != null ? title : '网站导航'}" required
                                       placeholder="请输入网站标题">
                            </div>
                            <button type="submit" class="btn btn-primary">
                                <i class="fa fa-save mr-1"></i>保存设置
                            </button>
                        </form>
                    </div>
                </div>

                <!-- 返回前台按钮 -->
                <!-- 在网站设置页面的按钮区域添加修改密码按钮 -->
                <div class="text-center mb-5">
                    <a href="/" class="btn btn-outline-primary me-2">
                        <i class="fa fa-home mr-1"></i>返回前台
                    </a>
                    <button type="button" class="btn btn-outline-warning me-2" data-bs-toggle="modal"
                            data-bs-target="#changePasswordModal">
                        <i class="fa fa-key mr-1"></i>修改密码
                    </button>
                    <a href="/logout" class="btn btn-outline-danger">
                        <i class="fa fa-sign-out-alt mr-1"></i>退出登录
                    </a>
                </div>
            </div>
            <!-- 文件管理页面 -->
            <!-- 在文件管理页面的表格中修改分类列 -->
            <div id="file-manage-page" class="page-content">
                <h2 class="page-title">文件管理</h2>
                <div class="card">
                    <div class="card-body">
                        <table id="fileTable" class="table table-striped">
                            <thead>
                            <tr>
                                <th>文件名</th>
                                <th>分类</th>  <!-- 现在显示两级分类信息 -->
                                <th>描述</th>
                                <th>大小</th>
                                <th>类型</th>
                                <th>下载次数</th>
                                <th>操作</th>
                            </tr>
                            </thead>
                            <tbody>
                            <tr th:each="file : ${files}">
                                <td th:text="${file.originalName}">文件名</td>
                                <!-- 在文件管理页面 -->
                                <td>
    <span th:if="${file.level1Name != null and file.categoryName != null}"
          th:text="${file.level1Name} + ' - ' + ${file.categoryName}">分类</span>
                                    <span th:if="${file.level1Name == null or file.categoryName == null}"
                                          class="text-muted">未分类</span>
                                </td>
                                <td th:text="${file.fileDescription}">描述</td>
                                <td th:data-size="${file.fileSize}" class="file-size">计算中...</td>
                                <td>
                        <span th:class="${'badge bg-' +
                                    (file.fileType == 'exe' ? 'danger' :
                                     file.fileType == 'msi' ? 'warning' :
                                     file.fileType == 'pdf' ? 'info' :
                                     file.fileType == 'jpg' || file.fileType == 'png' ? 'success' :
                                     'secondary')}"
                              th:text="${file.fileType}">类型</span>
                                </td>
                                <td th:text="${file.downloadCount}">0</td>
                                <td>
                                    <button class="btn btn-sm btn-primary btn-action edit-file-btn"
                                            th:data-id="${file.id}" th:data-name="${file.originalName}"
                                            th:data-category="${file.categoryId}" th:data-level1="${file.level1Id}"
                                            th:data-description="${file.fileDescription}" title="编辑">
                                        <i class="fa fa-edit"></i>
                                    </button>
                                    <a th:href="@{'api/file/download?fileId=' + ${file.id}}"
                                       class="btn btn-sm btn-success btn-action" title="下载">
                                        <i class="fa fa-download"></i>
                                    </a>
                                    <button class="btn btn-sm btn-danger btn-action delete-file-btn"
                                            th:data-id="${file.id}" th:data-name="${file.originalName}" title="删除">
                                        <i class="fa fa-trash"></i>
                                    </button>
                                </td>
                            </tr>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
            <!-- 分类管理页面 -->
            <div id="category-page" class="page-content">
                <h2 class="page-title">分类管理</h2>

                <!-- 一级分类管理 -->
                <div class="card mb-4">
                    <div class="card-header d-flex justify-content-between align-items-center">
                        <span><i class="fa fa-sitemap mr-2"></i>一级分类管理</span>
                        <button type="button" class="btn btn-primary btn-sm" id="add-level1-category-btn">
                            <i class="fas fa-plus me-1"></i>新增一级分类
                        </button>
                    </div>
                    <div class="card-body">
                        <table id="level1CategoryTable" class="table table-striped">
                            <thead>
                            <tr>
                                <th>编号</th>
                                <th>一级分类名称</th>
                                <th>排序顺序</th>
                                <th>二级分类数量</th>
                                <th>操作</th>
                            </tr>
                            </thead>
                            <tbody>
                            <tr th:each="level1 : ${level1Categories}">
                                <td th:text="${level1.id}">1</td>
                                <td th:text="${level1.name}">技术学习</td>
                                <td th:text="${level1.sortOrder}">0</td>
                                <td th:text="${level1.level2Categories != null ? level1.level2Categories.size() : 0}">
                                    0
                                </td>
                                <td>
                                    <button class="btn btn-sm btn-primary btn-action edit-level1-category-btn"
                                            th:data-id="${level1.id}" th:data-name="${level1.name}"
                                            th:data-sort="${level1.sortOrder}">
                                        <i class="fa fa-edit"></i>
                                    </button>
                                    <button class="btn btn-sm btn-danger btn-action delete-level1-category-btn"
                                            th:data-id="${level1.id}" th:data-name="${level1.name}">
                                        <i class="fa fa-trash"></i>
                                    </button>
                                </td>
                            </tr>
                            </tbody>
                        </table>
                    </div>
                </div>

                <!-- 二级分类管理 -->
                <div class="card">
                    <div class="card-header d-flex justify-content-between align-items-center">
                        <span><i class="fa fa-folder mr-2"></i>二级分类管理</span>
                        <button type="button" class="btn btn-primary btn-sm" id="add-level2-category-btn">
                            <i class="fas fa-plus me-1"></i>新增二级分类
                        </button>
                    </div>
                    <div class="card-body">
                        <table id="level2CategoryTable" class="table table-striped">
                            <thead>
                            <tr>
                                <th>编号</th>
                                <th>二级分类名称</th>
                                <th>所属一级分类</th>
                                <th>排序顺序</th>
                                <th>操作</th>
                            </tr>
                            </thead>
                            <tbody>
                            <!-- 直接遍历所有二级分类，不按一级分类分组 -->
                            <tr th:each="level2 : ${level2Categories}">
                                <td th:text="${level2.id}">1</td>
                                <td th:text="${level2.name}">编程语言</td>
                                <td th:text="${level2.level1Name}">技术学习</td>
                                <td th:text="${level2.sortOrder}">0</td>
                                <td>
                                    <button class="btn btn-sm btn-primary btn-action edit-level2-category-btn"
                                            th:data-id="${level2.id}" th:data-name="${level2.name}"
                                            th:data-level1-id="${level2.level1Id}" th:data-sort="${level2.sortOrder}">
                                        <i class="fa fa-edit"></i>
                                    </button>
                                    <button class="btn btn-sm btn-danger btn-action delete-level2-category-btn"
                                            th:data-id="${level2.id}" th:data-name="${level2.name}">
                                        <i class="fa fa-trash"></i>
                                    </button>
                                </td>
                            </tr>
                            <tr th:if="${level2Categories == null or level2Categories.isEmpty()}">
                                <td colspan="5" class="text-center text-muted">
                                    <i class="fa fa-folder-open me-2"></i>暂无二级分类
                                </td>
                            </tr>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>

            <!-- 文件上传页面 -->
            <div id="upload-page" class="page-content">
                <h2 class="page-title">文件上传</h2>
                <div class="card">
                    <div class="card-header">
                        <i class="fa fa-upload mr-2"></i>分片文件上传（支持10G大文件）
                    </div>
                    <div class="card-body">
                        <!-- 文件上传页面的分类选择 -->
                        <div class="row mb-3">
                            <div class="col-md-6">
                                <label for="upload-level1-category" class="form-label">选择一级分类 <span class="text-danger">*</span></label>
                                <select class="form-select" id="upload-level1-category" required>
                                    <option value="">请选择一级分类</option>
                                    <option th:each="level1 : ${level1Categories}"
                                            th:value="${level1.id}"
                                            th:text="${level1.name}">一级分类
                                    </option>
                                </select>
                            </div>
                            <div class="col-md-6">
                                <label for="upload-level2-category" class="form-label">选择二级分类 <span class="text-danger">*</span></label>
                                <select class="form-select" id="upload-level2-category" required>
                                    <option value="">请先选择一级分类</option>
                                </select>
                            </div>
                        </div>

                        <!-- 上传区域 -->
                        <div class="upload-area" id="dropArea"
                             style="border: 2px dashed #ccc; padding: 2rem; text-align: center; margin-bottom: 1rem; cursor: pointer;">
                            <p>拖拽文件到此处或点击选择文件</p>
                            <input type="file" id="fileInput" multiple style="display: none;">
                            <button class="btn btn-outline-primary mt-2"
                                    onclick="document.getElementById('fileInput').click()">选择文件
                            </button>
                        </div>

                        <!-- 上传列表（展示已选文件和上传中文件） -->
                        <div class="upload-list" id="uploadList"></div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<!-- 文件编辑模态框 -->
<div class="modal fade" id="editFileModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">编辑文件信息</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <form id="editFileForm" method="POST" action="/admin/file/update">
                <input type="hidden" id="editFileId" name="id">
                <div class="modal-body">
                    <div class="mb-3">
                        <label for="editFileName" class="form-label">文件名称 <span class="text-danger">*</span></label>
                        <input type="text" class="form-control" id="editFileName" name="originalName" required
                               placeholder="请输入文件名称" maxlength="500">
                    </div>
                    <div class="row mb-3">
                        <div class="col-md-6">
                            <label for="editFileLevel1Category" class="form-label">一级分类</label>
                            <select class="form-select" id="editFileLevel1Category" name="level1Id">
                                <option value="">请选择一级分类</option>
                                <option th:each="level1 : ${level1Categories}"
                                        th:value="${level1.id}"
                                        th:text="${level1.name}">一级分类
                                </option>
                            </select>
                        </div>
                        <div class="col-md-6">
                            <label for="editFileLevel2Category" class="form-label">二级分类 <span class="text-danger">*</span></label>
                            <select class="form-select" id="editFileLevel2Category" name="categoryId" required>
                                <option value="">请先选择一级分类</option>
                            </select>
                        </div>
                    </div>
                    <div class="mb-3">
                        <label for="fileDescription" class="form-label">文件描述</label>
                        <textarea class="form-control" id="fileDescription" name="fileDescription" rows="3"
                                  placeholder="请输入文件描述（可选）" maxlength="1000"></textarea>
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                    <button type="submit" class="btn btn-primary">保存</button>
                </div>
            </form>
        </div>
    </div>
</div>
<!-- 添加一级分类模态框 -->
<div class="modal fade" id="addLevel1CategoryModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">添加一级分类</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <form id="addLevel1CategoryForm" method="POST" action="/admin/category/level1/add">
                <div class="modal-body">
                    <div class="mb-3">
                        <label for="addLevel1CategoryName" class="form-label">一级分类名称 <span class="text-danger">*</span></label>
                        <input type="text" class="form-control" id="addLevel1CategoryName" name="name" required
                               placeholder="请输入一级分类名称" maxlength="100">
                    </div>
                    <div class="mb-3">
                        <label for="addLevel1CategorySort" class="form-label">排序顺序</label>
                        <input type="number" class="form-control" id="addLevel1CategorySort" name="sortOrder" min="0"
                               value="0" placeholder="数字越小排序越靠前">
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                    <button type="submit" class="btn btn-primary">保存</button>
                </div>
            </form>
        </div>
    </div>
</div>
<!-- 编辑一级分类模态框 -->
<div class="modal fade" id="editLevel1CategoryModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">编辑一级分类</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <form id="editLevel1CategoryForm" method="POST" action="/admin/category/level1/update">
                <input type="hidden" id="editLevel1CategoryId" name="id">
                <div class="modal-body">
                    <div class="mb-3">
                        <label for="editLevel1CategoryName" class="form-label">一级分类名称 <span class="text-danger">*</span></label>
                        <input type="text" class="form-control" id="editLevel1CategoryName" name="name" required
                               placeholder="请输入一级分类名称" maxlength="100">
                    </div>
                    <div class="mb-3">
                        <label for="editLevel1CategorySort" class="form-label">排序顺序</label>
                        <input type="number" class="form-control" id="editLevel1CategorySort" name="sortOrder" min="0"
                               placeholder="数字越小排序越靠前">
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                    <button type="submit" class="btn btn-primary">保存</button>
                </div>
            </form>
        </div>
    </div>
</div>

<!-- 添加二级分类模态框 -->
<div class="modal fade" id="addLevel2CategoryModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">添加二级分类</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <form id="addLevel2CategoryForm" method="POST" action="/admin/category/level2/add">
                <div class="modal-body">
                    <div class="mb-3">
                        <label for="addLevel2CategoryLevel1" class="form-label">所属一级分类 <span class="text-danger">*</span></label>
                        <select class="form-select" id="addLevel2CategoryLevel1" name="level1Id" required>
                            <option value="">请选择一级分类</option>
                            <option th:each="level1 : ${level1Categories}"
                                    th:value="${level1.id}"
                                    th:text="${level1.name}">一级分类
                            </option>
                        </select>
                    </div>
                    <div class="mb-3">
                        <label for="addLevel2CategoryName" class="form-label">二级分类名称 <span class="text-danger">*</span></label>
                        <input type="text" class="form-control" id="addLevel2CategoryName" name="name" required
                               placeholder="请输入二级分类名称" maxlength="100">
                    </div>
                    <div class="mb-3">
                        <label for="addLevel2CategorySort" class="form-label">排序顺序</label>
                        <input type="number" class="form-control" id="addLevel2CategorySort" name="sortOrder" min="0"
                               value="0" placeholder="数字越小排序越靠前">
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                    <button type="submit" class="btn btn-primary">保存</button>
                </div>
            </form>
        </div>
    </div>
</div>
<!-- 编辑二级分类模态框 -->
<div class="modal fade" id="editLevel2CategoryModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">编辑二级分类</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <form id="editLevel2CategoryForm" method="POST" action="/admin/category/level2/update">
                <input type="hidden" id="editLevel2CategoryId" name="id">
                <div class="modal-body">
                    <div class="mb-3">
                        <label for="editLevel2CategoryLevel1" class="form-label">所属一级分类 <span class="text-danger">*</span></label>
                        <select class="form-select" id="editLevel2CategoryLevel1" name="level1Id" required>
                            <option value="">请选择一级分类</option>
                            <option th:each="level1 : ${level1Categories}"
                                    th:value="${level1.id}"
                                    th:text="${level1.name}">一级分类
                            </option>
                        </select>
                    </div>
                    <div class="mb-3">
                        <label for="editLevel2CategoryName" class="form-label">二级分类名称 <span class="text-danger">*</span></label>
                        <input type="text" class="form-control" id="editLevel2CategoryName" name="name" required
                               placeholder="请输入二级分类名称" maxlength="100">
                    </div>
                    <div class="mb-3">
                        <label for="editLevel2CategorySort" class="form-label">排序顺序</label>
                        <input type="number" class="form-control" id="editLevel2CategorySort" name="sortOrder" min="0"
                               placeholder="数字越小排序越靠前">
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                    <button type="submit" class="btn btn-primary">保存</button>
                </div>
            </form>
        </div>
    </div>
</div>

<!-- 删除确认模态框 -->
<div class="modal fade" id="deleteConfirmModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">确认删除</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
                <p id="deleteConfirmText">确定要删除吗？</p>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                <button type="button" class="btn btn-danger" id="confirmDelete">确认删除</button>
            </div>
        </div>
    </div>
</div>
<!-- 隐藏的表单（用于发起POST请求） -->
<form id="deleteLevel1CategoryForm" method="POST" action="/admin/category/level1/delete">
    <input type="hidden" name="id" id="deleteLevel1CategoryId">
</form>

<form id="deleteLevel2CategoryForm" method="POST" action="/admin/category/level2/delete">
    <input type="hidden" name="id" id="deleteLevel2CategoryId">
</form>

<form id="deleteFileForm" method="POST" action="/admin/file/delete">
    <input type="hidden" name="id" id="deleteFileId">
</form>
<!-- 修改密码模态框 -->
<div class="modal fade" id="changePasswordModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">修改密码</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
                <!-- 修正action路径，使用Thymeleaf语法 -->
                <form id="changePasswordForm" th:action="@{/admin/change-password}" method="post">
                    <div class="mb-3">
                        <label for="currentPassword" class="form-label">当前密码</label>
                        <div class="input-group">
                            <input type="password" class="form-control" id="currentPassword" name="currentPassword"
                                   required>
                            <button type="button" class="btn btn-outline-secondary toggle-password"
                                    data-target="currentPassword">
                                <i class="fa fa-eye"></i>
                            </button>
                        </div>
                    </div>
                    <div class="mb-3">
                        <label for="newPassword" class="form-label">新密码</label>
                        <div class="input-group">
                            <input type="password" class="form-control" id="newPassword" name="newPassword" required
                                   minlength="6">
                            <button type="button" class="btn btn-outline-secondary toggle-password"
                                    data-target="newPassword">
                                <i class="fa fa-eye"></i>
                            </button>
                        </div>
                        <div class="form-text">密码长度至少6位</div>
                    </div>
                    <div class="mb-3">
                        <label for="confirmPassword" class="form-label">确认新密码</label>
                        <div class="input-group">
                            <input type="password" class="form-control" id="confirmPassword" required>
                            <button type="button" class="btn btn-outline-secondary toggle-password"
                                    data-target="confirmPassword">
                                <i class="fa fa-eye"></i>
                            </button>
                        </div>
                        <div class="invalid-feedback" id="confirmPasswordError">两次输入的密码不一致</div>
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                <button type="button" class="btn btn-primary" id="submitChangePassword">确认修改</button>
            </div>
        </div>
    </div>
</div>
<div id="thymeleaf-data-container" style="display: none;">
    <input type="hidden" id="thymeleaf-data-level1Categories" th:value="${#strings.toString(level1Categories)}">
</div>
<!-- Bootstrap JS -->
<script th:src="@{/js/jQuery.js}"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script th:src="@{/js/bootstrap.js}"></script>
<script th:src="@{/js/tables.js}"></script>

<script>
    // 显示/隐藏密码功能
    document.querySelectorAll('.toggle-password').forEach(button => {
        button.addEventListener('click', function () {
            const targetId = this.getAttribute('data-target');
            const passwordInput = document.getElementById(targetId);
            const icon = this.querySelector('i');

            if (passwordInput.type === 'password') {
                passwordInput.type = 'text';
                icon.classList.remove('fa-eye');
                icon.classList.add('fa-eye-slash');
            } else {
                passwordInput.type = 'password';
                icon.classList.remove('fa-eye-slash');
                icon.classList.add('fa-eye');
            }
        });
    });

    // 密码确认验证
    document.getElementById('confirmPassword').addEventListener('input', function () {
        const newPassword = document.getElementById('newPassword').value;
        const confirmPassword = this.value;
        const errorElement = document.getElementById('confirmPasswordError');

        if (newPassword !== confirmPassword) {
            this.classList.add('is-invalid');
            errorElement.style.display = 'block';
        } else {
            this.classList.remove('is-invalid');
            errorElement.style.display = 'none';
        }
    });

    // 表单提交
    document.getElementById('submitChangePassword').addEventListener('click', function () {
        const currentPassword = document.getElementById('currentPassword').value;
        const newPassword = document.getElementById('newPassword').value;
        const confirmPassword = document.getElementById('confirmPassword').value;

        // 验证表单
        if (!validatePasswordForm(currentPassword, newPassword, confirmPassword)) {
            return;
        }

        // 使用Fetch API（现代浏览器推荐）
        fetch('/admin/change-password', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            },
            body: new URLSearchParams({
                currentPassword: currentPassword,
                newPassword: newPassword
            })
        })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    // 关闭模态框
                    const modal = bootstrap.Modal.getInstance(document.getElementById('changePasswordModal'));
                    modal.hide();
                    // 显示成功消息
                    showToast('success', data.message);
                    // 清空表单
                    document.getElementById('changePasswordForm').reset();
                } else {
                    showToast('error', data.message);
                }
            })
            .catch(error => {
                console.error('Error:', error);
                showToast('error', '修改密码失败: ' + error.message);
            });
    });

    function validatePasswordForm(currentPassword, newPassword, confirmPassword) {
        if (!currentPassword) {
            showToast('error', '请输入当前密码');
            return false;
        }

        if (!newPassword || newPassword.length < 6) {
            showToast('error', '新密码长度至少6位');
            return false;
        }

        if (newPassword !== confirmPassword) {
            showToast('error', '两次输入的新密码不一致');
            return false;
        }

        return true;
    }

    // 模态框显示时重置表单
    document.getElementById('changePasswordModal').addEventListener('show.bs.modal', function () {
        document.getElementById('changePasswordForm').reset();
        document.getElementById('confirmPassword').classList.remove('is-invalid');
        document.getElementById('confirmPasswordError').style.display = 'none';
    });

    // 处理消息提示
    document.addEventListener('DOMContentLoaded', function () {
        // 显示flash消息
        const message = /*[[${message}]]*/ null;
        const error = /*[[${error}]]*/ null;
    });

    // 显示Toast消息函数
    function showToast(type, message) {
        // 创建Toast容器（如果不存在）
        let toastContainer = document.getElementById('toast-container');
        if (!toastContainer) {
            toastContainer = document.createElement('div');
            toastContainer.id = 'toast-container';
            toastContainer.className = 'position-fixed top-0 end-0 p-3';
            toastContainer.style.zIndex = '9999';
            document.body.appendChild(toastContainer);
        }

        // 创建Toast元素
        const toastId = 'toast-' + Date.now();
        const toastHtml = `
        <div id="${toastId}" class="toast align-items-center text-white bg-${type === 'success' ? 'success' : 'danger'} border-0" role="alert">
            <div class="d-flex">
                <div class="toast-body">
                    <i class="fa ${type === 'success' ? 'fa-check-circle' : 'fa-exclamation-circle'} me-2"></i>
                    ${message}
                </div>
                <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
            </div>
        </div>
    `;

        toastContainer.insertAdjacentHTML('beforeend', toastHtml);

        // 显示Toast
        const toastElement = document.getElementById(toastId);
        const toast = new bootstrap.Toast(toastElement);
        toast.show();

        // 自动移除Toast
        toastElement.addEventListener('hidden.bs.toast', function () {
            this.remove();
        });
    }
</script>
<script>
    // 页面加载完成后执行
    document.addEventListener('DOMContentLoaded', function () {
        // 初始化页面导航
        initNavigation();

        // 初始化分类管理功能
        initCategoryManagement();

        // 初始化文件管理功能
        initFileManagement();

        // 初始化DataTables
        initDataTables();

        // 格式化所有文件大小
        formatAllFileSizes();

        // 初始化分类联动
        initCategoryLinkage();
    });

    // 智能格式化文件大小（B→KB→MB→GB→TB）
    function formatFileSize(bytes) {
        if (bytes === 0) return '0 Bytes';

        // 定义单位和换算比例
        const units = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
        const k = 1024;

        // 计算最合适的单位
        const i = Math.floor(Math.log(bytes) / Math.log(k));

        // 计算并保留两位小数
        const size = parseFloat((bytes / Math.pow(k, i)).toFixed(2));

        // 返回格式化后的字符串
        return `${size} ${units[i]}`;
    }

    // 更新二级分类选项（AJAX版本）
    function updateLevel2Options(level1Id, level2Select) {
        console.log('更新二级分类，一级分类ID:', level1Id);

        // 清空现有选项
        level2Select.innerHTML = '<option value="">请选择二级分类</option>';

        if (!level1Id) return;

        // 显示加载中
        const loadingOption = document.createElement('option');
        loadingOption.value = "";
        loadingOption.textContent = "加载中...";
        loadingOption.disabled = true;
        level2Select.appendChild(loadingOption);

        // 使用AJAX获取二级分类
        fetch('/admin/category/level2/by-level1?level1Id=' + level1Id)
            .then(response => response.json())
            .then(level2Categories => {
                // 清空选项
                level2Select.innerHTML = '<option value="">请选择二级分类</option>';

                if (level2Categories && level2Categories.length > 0) {
                    level2Categories.forEach(level2 => {
                        const option = document.createElement('option');
                        option.value = level2.id;
                        option.textContent = level2.name;
                        level2Select.appendChild(option);
                    });
                } else {
                    const option = document.createElement('option');
                    option.value = "";
                    option.textContent = "该一级分类下暂无二级分类";
                    level2Select.appendChild(option);
                }
            })
            .catch(error => {
                console.error('加载二级分类失败:', error);
                level2Select.innerHTML = '<option value="">加载失败</option>';
            });
    }

    // 初始化分类联动选择
    function initCategoryLinkage() {
        // 上传页面的一级分类变化时更新二级分类
        const uploadLevel1Select = document.getElementById('upload-level1-category');
        const uploadLevel2Select = document.getElementById('upload-level2-category');

        if (uploadLevel1Select) {
            uploadLevel1Select.addEventListener('change', function () {
                updateLevel2Options(this.value, uploadLevel2Select);
            });
        }

        // 编辑文件页面的一级分类变化时更新二级分类
        const editLevel1Select = document.getElementById('editFileLevel1Category');
        const editLevel2Select = document.getElementById('editFileLevel2Category');

        if (editLevel1Select) {
            editLevel1Select.addEventListener('change', function () {
                updateLevel2Options(this.value, editLevel2Select);
            });
        }

        // 编辑二级分类页面的一级分类变化时更新二级分类
        const editLevel2Level1Select = document.getElementById('editLevel2CategoryLevel1');

        if (editLevel2Level1Select) {
            editLevel2Level1Select.addEventListener('change', function () {
                // 这里不需要更新二级分类，因为是在编辑已有的二级分类
            });
        }
    }

    // 格式化所有文件列表中的文件大小
    function formatAllFileSizes() {
        document.querySelectorAll('.file-size').forEach(element => {
            // 获取原始字节数
            const fileSizeBytes = parseInt(element.getAttribute('data-size'));

            // 格式化并显示
            if (!isNaN(fileSizeBytes)) {
                element.textContent = formatFileSize(fileSizeBytes);
            } else {
                element.textContent = '未知大小';
            }
        });
    }

    // 页面导航功能
    // 页面导航功能
    function initNavigation() {
        // 侧边栏导航点击事件
        document.querySelectorAll('.sidebar .nav-link').forEach(link => {
            link.addEventListener('click', function (e) {
                e.preventDefault();

                // 移除所有active类
                document.querySelectorAll('.sidebar .nav-link').forEach(navLink => {
                    navLink.classList.remove('active');
                });

                // 添加active类到当前点击的链接
                this.classList.add('active');

                // 隐藏所有页面内容
                document.querySelectorAll('.page-content').forEach(page => {
                    page.classList.remove('active');
                });

                // 显示对应的页面内容
                const pageId = this.getAttribute('data-page');
                const targetPage = document.getElementById(pageId);

                // 添加安全检查
                if (targetPage) {
                    targetPage.classList.add('active');
                } else {
                    console.error('页面未找到:', pageId);
                    // 默认显示第一个页面
                    document.querySelector('.page-content').classList.add('active');
                }
            });
        });

        // 移动端菜单切换
        const mobileMenuToggle = document.querySelector('.mobile-menu-toggle');
        const sidebar = document.querySelector('.sidebar');

        if (mobileMenuToggle && sidebar) {
            mobileMenuToggle.addEventListener('click', function () {
                sidebar.classList.toggle('show');
            });
        }
    }

    // 分类管理功能
    function initCategoryManagement() {
        // 新增一级分类按钮
        const addLevel1CategoryBtn = document.getElementById('add-level1-category-btn');
        if (addLevel1CategoryBtn) {
            addLevel1CategoryBtn.addEventListener('click', function () {
                // 清空表单
                document.getElementById('addLevel1CategoryName').value = '';
                document.getElementById('addLevel1CategorySort').value = '0';

                // 显示模态框
                const modal = new bootstrap.Modal(document.getElementById('addLevel1CategoryModal'));
                modal.show();
            });
        }

        // 新增二级分类按钮
        const addLevel2CategoryBtn = document.getElementById('add-level2-category-btn');
        if (addLevel2CategoryBtn) {
            addLevel2CategoryBtn.addEventListener('click', function () {
                // 清空表单
                document.getElementById('addLevel2CategoryName').value = '';
                document.getElementById('addLevel2CategorySort').value = '0';
                document.getElementById('addLevel2CategoryLevel1').selectedIndex = 0;

                // 显示模态框
                const modal = new bootstrap.Modal(document.getElementById('addLevel2CategoryModal'));
                modal.show();
            });
        }

        // 使用事件委托绑定分类操作按钮
        document.addEventListener('click', function (e) {
            // 一级分类编辑按钮
            if (e.target.closest('.edit-level1-category-btn')) {
                const btn = e.target.closest('.edit-level1-category-btn');
                const id = btn.getAttribute('data-id');
                const name = btn.getAttribute('data-name');
                const sort = btn.getAttribute('data-sort');

                document.getElementById('editLevel1CategoryId').value = id;
                document.getElementById('editLevel1CategoryName').value = name;
                document.getElementById('editLevel1CategorySort').value = sort;

                const modal = new bootstrap.Modal(document.getElementById('editLevel1CategoryModal'));
                modal.show();
            }

            // 一级分类删除按钮
            if (e.target.closest('.delete-level1-category-btn')) {
                const btn = e.target.closest('.delete-level1-category-btn');
                const id = btn.getAttribute('data-id');
                const name = btn.getAttribute('data-name');

                document.getElementById('deleteConfirmText').textContent =
                    `确定要删除一级分类 "${name}" 吗？该分类下的所有二级分类也将被删除。`;

                const modal = new bootstrap.Modal(document.getElementById('deleteConfirmModal'));
                modal.show();

                // 设置确认删除操作
                document.getElementById('confirmDelete').onclick = function () {
                    document.getElementById('deleteLevel1CategoryId').value = id;
                    document.getElementById('deleteLevel1CategoryForm').submit();
                };
            }

            // 二级分类编辑按钮
            if (e.target.closest('.edit-level2-category-btn')) {
                const btn = e.target.closest('.edit-level2-category-btn');
                const id = btn.getAttribute('data-id');
                const name = btn.getAttribute('data-name');
                const level1Id = btn.getAttribute('data-level1-id');
                const sort = btn.getAttribute('data-sort');

                document.getElementById('editLevel2CategoryId').value = id;
                document.getElementById('editLevel2CategoryName').value = name;
                document.getElementById('editLevel2CategorySort').value = sort;

                // 设置一级分类选中
                const level1Select = document.getElementById('editLevel2CategoryLevel1');
                for (let i = 0; i < level1Select.options.length; i++) {
                    if (level1Select.options[i].value === level1Id) {
                        level1Select.selectedIndex = i;
                        break;
                    }
                }

                const modal = new bootstrap.Modal(document.getElementById('editLevel2CategoryModal'));
                modal.show();
            }

            // 二级分类删除按钮
            if (e.target.closest('.delete-level2-category-btn')) {
                const btn = e.target.closest('.delete-level2-category-btn');
                const id = btn.getAttribute('data-id');
                const name = btn.getAttribute('data-name');

                document.getElementById('deleteConfirmText').textContent =
                    `确定要删除二级分类 "${name}" 吗？该分类下的文件将变为未分类状态。`;

                const modal = new bootstrap.Modal(document.getElementById('deleteConfirmModal'));
                modal.show();

                // 设置确认删除操作
                document.getElementById('confirmDelete').onclick = function () {
                    document.getElementById('deleteLevel2CategoryId').value = id;
                    document.getElementById('deleteLevel2CategoryForm').submit();
                };
            }
        });
    }


    // 文件管理功能
    function initFileManagement() {
        // 使用事件委托绑定文件编辑按钮
        document.addEventListener('click', function (e) {
            // 编辑文件按钮逻辑
            if (e.target.closest('.edit-file-btn')) {
                const btn = e.target.closest('.edit-file-btn');
                const fileId = btn.getAttribute('data-id');
                const fileName = btn.getAttribute('data-name');
                const categoryId = btn.getAttribute('data-category');
                const level1Id = btn.getAttribute('data-level1');
                const description = btn.getAttribute('data-description');

                // 填充表单数据
                document.getElementById('editFileId').value = fileId;
                document.getElementById('editFileName').value = fileName;
                document.getElementById('fileDescription').value = description || '';

                // 设置一级分类
                const level1Select = document.getElementById('editFileLevel1Category');
                if (level1Id) {
                    for (let i = 0; i < level1Select.options.length; i++) {
                        if (level1Select.options[i].value === level1Id) {
                            level1Select.selectedIndex = i;
                            // 触发change事件来更新二级分类
                            level1Select.dispatchEvent(new Event('change'));
                            break;
                        }
                    }
                }

                // 设置二级分类（需要等待一级分类更新完成）
                setTimeout(() => {
                    const level2Select = document.getElementById('editFileLevel2Category');
                    if (categoryId) {
                        for (let i = 0; i < level2Select.options.length; i++) {
                            if (level2Select.options[i].value === categoryId) {
                                level2Select.selectedIndex = i;
                                break;
                            }
                        }
                    }
                }, 100);

                // 显示编辑模态框
                const editModal = new bootstrap.Modal(document.getElementById('editFileModal'));
                editModal.show();
            }

            // 删除文件按钮逻辑（保持不变）
            if (e.target.closest('.delete-file-btn')) {
                const btn = e.target.closest('.delete-file-btn');
                const fileId = btn.getAttribute('data-id');
                const fileName = btn.getAttribute('data-name');

                document.getElementById('deleteConfirmText').textContent =
                    `确定要删除文件 "${fileName}" 吗？此操作不可恢复。`;

                const deleteModal = new bootstrap.Modal(document.getElementById('deleteConfirmModal'));
                deleteModal.show();

                document.getElementById('confirmDelete').onclick = function () {
                    document.getElementById('deleteFileId').value = fileId;
                    document.getElementById('deleteFileForm').submit();
                };
            }
        });

    }

    // 初始化DataTables
    function initDataTables() {
        // 等待表格渲染完成后再初始化
        setTimeout(() => {
            if (typeof simpleDatatables !== 'undefined') {
                // 文件表格
                if (document.getElementById('fileTable')) {
                    new simpleDatatables.DataTable("#fileTable", {
                        perPage: 10,
                        perPageSelect: [5, 10, 20, 50],
                        searchable: true,
                        sortable: true,
                        labels: {
                            placeholder: "搜索文件...",
                            noRows: "没有找到文件",
                            info: "显示第 {start} 至 {end} 条记录，共 {rows} 条"
                        }
                    });
                }

                // 分类表格
                if (document.getElementById('categoryTable')) {
                    new simpleDatatables.DataTable("#categoryTable", {
                        perPage: 10,
                        perPageSelect: [5, 10, 20, 50],
                        searchable: true,
                        sortable: true,
                        labels: {
                            placeholder: "搜索分类...",
                            noRows: "没有找到分类",
                            info: "显示第 {start} 至 {end} 条记录，共 {rows} 条"
                        }
                    });
                }
            }
        }, 100);
    }

    // 刷新文件列表
    function refreshFileList() {
        location.reload();
    }

    // 显示全局通知
    function showGlobalNotification(message) {
        const notification = document.getElementById('globalNotification');
        const messageElement = document.getElementById('notificationMessage');

        messageElement.textContent = message;
        notification.classList.add('show');

        // 3秒后自动关闭
        setTimeout(() => {
            notification.classList.remove('show');
        }, 3000);
    }

</script>

<script>
    // 全局变量：仅保留核心必要变量
    const CHUNK_SIZE = 5 * 1024 * 1024; // 5MB分片大小
    let uploadQueue = []; // 上传队列（待上传/上传中文件）
    let currentUpload = null; // 当前正在上传的文件
    let selectedFiles = []; // 已选择待上传的文件（未加入上传队列）

    // 页面加载完成初始化
    document.addEventListener('DOMContentLoaded', function () {
        const dropArea = document.getElementById('dropArea');
        const fileInput = document.getElementById('fileInput');

        // 1. 拖拽事件处理（防止默认行为）
        ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
            dropArea.addEventListener(eventName, preventDefaults, false);
        });

        // 2. 拖拽区域高亮效果
        ['dragenter', 'dragover'].forEach(eventName => {
            dropArea.addEventListener(eventName, highlight, false);
        });
        ['dragleave', 'drop'].forEach(eventName => {
            dropArea.addEventListener(eventName, unhighlight, false);
        });

        // 3. 文件选择/拖放处理
        dropArea.addEventListener('drop', handleDrop, false);
        fileInput.addEventListener('change', handleFileSelect, false);

        // 4. 初始化时渲染已选文件列表（若有）
        displaySelectedFiles();
    });

    // ---------------------- 基础工具函数 ----------------------
    // 防止浏览器默认拖拽行为
    function preventDefaults(e) {
        e.preventDefault();
        e.stopPropagation();
    }

    // 拖拽区域高亮
    function highlight() {
        document.getElementById('dropArea').style.borderColor = '#4CAF50';
        document.getElementById('dropArea').style.backgroundColor = 'rgba(76, 175, 80, 0.05)';
    }

    // 拖拽区域取消高亮
    function unhighlight() {
        document.getElementById('dropArea').style.borderColor = '#ccc';
        document.getElementById('dropArea').style.backgroundColor = 'transparent';
    }

    // 生成文件唯一ID
    function generateFileId() {
        return Date.now() + '-' + Math.random().toString(36).substr(2, 9);
    }

    // 提取文件后缀名（如exe、msi、pdf）
    function getFileExtension(fileName) {
        // 处理无后缀名的情况
        if (!fileName.includes('.')) return 'unknown';
        // 提取最后一个.后的字符，转为小写
        return fileName.split('.').pop().toLowerCase();
    }

    // ---------------------- 文件选择与列表展示 ----------------------
    // 处理拖放文件
    function handleDrop(e) {
        const dt = e.dataTransfer;
        const files = dt.files;
        handleFiles(files);
    }

    // 处理选择文件
    function handleFileSelect(e) {
        const files = e.target.files;
        handleFiles(files);
        // 清空input值，避免重复选择同一文件时不触发change事件
        e.target.value = '';
    }

    // 处理选中的文件（去重后加入已选列表）
    function handleFiles(files) {
        if (files.length === 0) return;

        for (let i = 0; i < files.length; i++) {
            const file = files[i];
            // 去重逻辑：按文件名+文件大小判断（避免同一文件重复添加）
            const isDuplicate = selectedFiles.some(item =>
                item.file.name === file.name && item.file.size === file.size
            );
            if (!isDuplicate) {
                selectedFiles.push({
                    fileId: generateFileId(), // 生成唯一ID
                    file: file,
                    fileType: getFileExtension(file.name), // 存储文件后缀名
                    fileDescription: "" // 新增：文件描述字段，默认空
                });
            }
        }

        // 刷新已选文件列表展示
        displaySelectedFiles();
    }

    // 展示已选文件列表（含单个取消按钮 + 批量开始上传按钮）
    function displaySelectedFiles() {
        const uploadList = document.getElementById('uploadList');
        uploadList.innerHTML = '';

        // 1. 若无可选文件，直接返回
        if (selectedFiles.length === 0) {
            uploadList.innerHTML = '<div class="text-muted text-center py-3">暂无已选择的文件</div>';
            return;
        }

        // 2. 渲染每个已选文件项（新增：文件描述输入框）
        selectedFiles.forEach((fileItem, index) => {
            const {fileId, file, fileType, fileDescription} = fileItem;
            const item = document.createElement('div');
            item.className = 'upload-item d-flex flex-column p-3 border rounded mb-2'; // 改为flex-column垂直布局，容纳输入框
            item.id = `selected-file-${fileId}`;

            // 文件信息 + 取消按钮（新增：文件描述输入框）
            item.innerHTML = `
                <div class="d-flex justify-content-between align-items-center mb-2">
                    <div>
                        <strong>${file.name}</strong>
                        <span class="text-muted ms-2">(${formatFileSize(file.size)} · ${fileType})</span>
                    </div>
                    <button class="btn btn-sm btn-danger cancel-selected-file"
                            data-index="${index}"
                            title="取消选择">
                        <i class="fa fa-times"></i> 取消
                    </button>
                </div>
                <!-- 新增：文件描述输入框 -->
                <div class="mt-2">
                    <label class="form-label text-sm text-muted">文件描述</label>
                    <input type="text"
                           class="form-control file-description-input"
                           data-index="${index}"
                           placeholder="请输入文件描述（可选）"
                           value="${fileDescription || ''}">
                </div>
            `;

            uploadList.appendChild(item);

            // 绑定取消按钮事件（删除单个已选文件）
            item.querySelector('.cancel-selected-file').addEventListener('click', function () {
                const index = parseInt(this.getAttribute('data-index'));
                removeSelectedFile(index);
            });

            // 新增：绑定描述输入框事件，实时同步值到selectedFiles
            item.querySelector('.file-description-input').addEventListener('input', function () {
                const index = parseInt(this.getAttribute('data-index'));
                selectedFiles[index].fileDescription = this.value.trim(); // 实时更新描述
            });
        });

        // 3. 渲染批量开始上传按钮（不变）
        const buttonContainer = document.createElement('div');
        buttonContainer.className = 'text-center mt-3';
        buttonContainer.innerHTML = `
            <button class="btn btn-primary" id="batch-upload-btn">
                <i class="fa fa-upload"></i> 开始上传所有文件
            </button>
        `;
        uploadList.appendChild(buttonContainer);

        // 绑定批量上传按钮事件（不变）
        document.getElementById('batch-upload-btn').addEventListener('click', startBatchUpload);
    }

    // 移除单个已选文件
    function removeSelectedFile(index) {
        selectedFiles.splice(index, 1);
        displaySelectedFiles();
    }

    // ---------------------- 批量上传核心逻辑 ----------------------
    // 开始批量上传（验证分类→加入上传队列→清空已选列表→启动队列）
    async function startBatchUpload() {
        // 1. 验证分类是否选择
        const level1Select = document.getElementById('upload-level1-category');
        const level2Select = document.getElementById('upload-level2-category');

        const level1Id = level1Select.value;
        const level2Id = level2Select.value;

        if (!level1Id || !level2Id) {
            alert('请先选择完整的一级和二级分类！');
            return;
        }


        // 4. 将已选文件加入上传队列，并生成上传中UI
        selectedFiles.forEach(fileItem => {
            const {fileId, file, fileType, fileDescription} = fileItem;
            const totalChunks = Math.ceil(file.size / CHUNK_SIZE);

            // 加入上传队列
            uploadQueue.push({
                id: fileId,
                file: file,
                fileType: fileType, // 传递文件后缀名到后端
                categoryId: level2Id, // 携带分类ID
                totalChunks: totalChunks,
                uploadedChunks: [],
                fileDescription: fileDescription || "文件描述",
                progress: 0
            });

            // 生成上传中UI（替换已选列表）
            createUploadingItem(fileId, file.name, file.size);
        });

        // 5. 清空已选文件列表（隐藏取消按钮和批量上传按钮）
        selectedFiles = [];
        const uploadList = document.getElementById('uploadList');
        uploadList.innerHTML = '';
        // 重新渲染上传队列（含上传中文件）
        renderUploadQueue();

        // 6. 启动上传队列（挨个上传）
        processUploadQueue();
    }

    // 渲染上传队列（上传中/待上传文件）
    function renderUploadQueue() {
        const uploadList = document.getElementById('uploadList');
        uploadList.innerHTML = '';

        // 若队列空，显示提示
        if (uploadQueue.length === 0) {
            uploadList.innerHTML = '<div class="text-muted text-center py-3">暂无上传任务</div>';
            return;
        }

        // 渲染每个上传任务
        uploadQueue.forEach(fileInfo => {
            const {id, file, progress} = fileInfo;
            const item = document.getElementById(`uploading-item-${id}`);
            // 若已存在则更新进度，不存在则创建
            if (item) {
                updateProgress(id, progress);
            } else {
                createUploadingItem(id, file.name, file.size);
            }
        });
    }

    // 创建上传中文件的UI（确保进度条显示）
    function createUploadingItem(fileId, fileName, fileSize) {
        const uploadList = document.getElementById('uploadList');
        const item = document.createElement('div');
        item.className = 'uploading-item border rounded p-3 mb-2';
        item.id = `uploading-item-${fileId}`;

        // 确保进度条元素可见
        item.innerHTML = `
    <div class="d-flex justify-content-between align-items-center mb-2">
        <strong>${fileName}</strong>
        <span class="text-muted">(${formatFileSize(fileSize)})</span>
    </div>
    <!-- 进度条容器 - 强制显示 -->
    <div class="progress mb-2" style="display: block !important; visibility: visible !important;">
        <div id="progress-${fileId}"
             class="progress-bar bg-success"
             role="progressbar"
             style="width: 0%; display: flex !important;"
             aria-valuenow="0"
             aria-valuemin="0"
             aria-valuemax="100">
            0%
        </div>
    </div>
    <!-- 状态与速度 -->
    <div class="d-flex justify-content-between text-sm text-muted">
        <div id="status-${fileId}">等待上传</div>
        <div id="speed-${fileId}">0 KB/s</div>
    </div>
`;

        uploadList.appendChild(item);

        // 调试用：确认元素已添加到DOM
        console.log(`创建上传项: #uploading-item-${fileId}`, item);
    }

    // 处理上传队列（递归挨个上传）
    async function processUploadQueue() {
        // 若有文件正在上传或队列为空，终止递归
        if (currentUpload || uploadQueue.length === 0) {
            // 队列为空时更新提示
            if (uploadQueue.length === 0) {
                renderUploadQueue();
            }
            return;
        }

        // 取出队列第一个文件开始上传
        currentUpload = uploadQueue[0];
        await uploadSingleFile(currentUpload);

        // 上传完成后移除当前文件，重置currentUpload，继续下一个
        uploadQueue.shift();
        currentUpload = null;
        processUploadQueue();
    }

    // ---------------------- 单个文件上传逻辑 ----------------------
    // 上传单个文件（分片上传+合并）
    async function uploadSingleFile(fileInfo) {
        const {id, file, categoryId, fileType, totalChunks, fileDescription} = fileInfo;
        let fileMd5 = '';

        try {
            // 1. 计算文件MD5（用于分片校验）
            updateUploadStatus(id, '计算文件MD5...');
            fileMd5 = await calculateFileMd5(file);

            // 2. 检查已上传分片（断点续传）
            updateUploadStatus(id, '检查已上传分片...');
            const uploadedChunks = await checkUploadedChunks(fileMd5);
            fileInfo.uploadedChunks = uploadedChunks;

            // 3. 计算初始进度
            const initialProgress = Math.round((uploadedChunks.length / totalChunks) * 100);
            updateProgress(id, initialProgress);

            // 4. 上传未完成的分片
            updateUploadStatus(id, '正在上传...');
            for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) {
                // 跳过已上传的分片
                if (uploadedChunks.includes(chunkIndex)) continue;

                // 切割分片
                const chunk = file.slice(
                    chunkIndex * CHUNK_SIZE,
                    Math.min((chunkIndex + 1) * CHUNK_SIZE, file.size)
                );

                // 上传分片（获取上传速度）
                const speedMB = await uploadChunk(chunk, fileMd5, chunkIndex, totalChunks, id, fileType);
                updateUploadSpeed(id, speedMB);

                // 更新已上传分片和进度
                fileInfo.uploadedChunks.push(chunkIndex);
                const progress = Math.round((fileInfo.uploadedChunks.length / totalChunks) * 100);
                fileInfo.progress = progress;
                updateProgress(id, progress);
            }

            // 5. 合并分片
            updateUploadStatus(id, '正在合并文件...');
            await mergeChunks(fileMd5, file.name, fileType, file.size, categoryId, fileDescription);

            // 6. 上传完成
            updateUploadStatus(id, '<span class="text-success">上传完成</span>');

            // 显示全局上传完成弹窗
            showGlobalNotification(`文件 "${file.name}" 上传完成`);

            // 3秒后移除上传完成的UI
            setTimeout(() => {
                const item = document.getElementById(`uploading-item-${id}`);
                if (item) item.remove();
                renderUploadQueue();

                // 刷新文件列表并跳转到文件管理页面
                location.reload();
                // 自动切换到文件管理页面
                document.querySelectorAll('.sidebar .nav-link').forEach(link => {
                    link.classList.remove('active');
                });
                document.querySelectorAll('.page-content').forEach(page => {
                    page.classList.remove('active');
                });
                document.querySelector('[data-page="file-manage-page"]').classList.add('active');
                document.getElementById('file-manage-page').classList.add('active');
            }, 3000);



        } catch (error) {
            // 上传失败处理
            console.error(`文件 ${file.name} 上传失败:`, error);
            updateUploadStatus(id, `<span class="text-danger">上传失败: ${error.message}</span>`);
            // 显示重新上传按钮
            const item = document.getElementById(`uploading-item-${id}`);
            if (item && !item.querySelector('.retry-upload-btn')) {
                const retryBtn = document.createElement('button');
                retryBtn.className = 'btn btn-sm btn-outline-primary mt-2 retry-upload-btn';
                retryBtn.innerHTML = '<i class="fa fa-refresh"></i> 重新上传';
                retryBtn.addEventListener('click', function () {
                    // 重新加入队列并启动
                    uploadQueue.unshift(fileInfo);
                    processUploadQueue();
                    this.remove();
                });
                item.appendChild(retryBtn);
            }
        }
    }

    // 计算文件MD5（简化版）
    async function calculateFileMd5(file) {
        // 使用文件大小和修改时间生成唯一标识
        const uniqueString = `${file.size}-${file.lastModified}`;
        return btoa(uniqueString).substr(0, 32);
    }

    // 检查已上传的分片
    async function checkUploadedChunks(fileMd5) {
        try {
            const response = await fetch(`/api/file/chunks?fileMd5=${fileMd5}`);
            if (!response.ok) throw new Error('请求失败');
            const data = await response.json();
            return data.uploadedChunks || [];
        } catch (error) {
            console.error('检查分片失败:', error);
            return []; // 异常时默认无已上传分片
        }
    }

    // 上传单个分片
    async function uploadChunk(chunk, fileMd5, chunkIndex, totalChunks, fileId, fileType) {
        const formData = new FormData();
        formData.append('file', chunk);
        formData.append('fileMd5', fileMd5);
        formData.append('chunkIndex', chunkIndex);
        formData.append('totalChunks', totalChunks);
        formData.append('fileType', fileType);

        const startTime = Date.now();

        // 发送分片请求
        const response = await fetch('/api/file/upload/chunk', {
            method: 'POST',
            body: formData
        });

        const endTime = Date.now();
        const duration = (endTime - startTime) / 1000; // 耗时（秒）
        const chunkSizeMB = chunk.size / (1024 * 1024); // 分片大小（MB）
        const speedMB = chunkSizeMB / duration; // 上传速度（MB/s）

        // 校验响应
        if (!response.ok) throw new Error('分片上传失败');
        const result = await response.json();
        if (!result.success) throw new Error(result.message || '分片上传失败');

        return speedMB; // 返回速度用于显示
    }

    // 合并分片
    async function mergeChunks(fileMd5, fileName, fileType, fileSize, categoryId, fileDescription) {
        const response = await fetch('/api/file/merge', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            },
            body: new URLSearchParams({
                fileMd5: fileMd5,
                fileName: fileName,
                fileType: fileType,
                fileSize: fileSize.toString(),
                categoryId: categoryId || '',
                fileDescription: fileDescription || "文件描述"
            })
        });

        if (!response.ok) throw new Error('文件合并请求失败');
        const result = await response.json();
        if (!result.success) throw new Error(result.message || '文件合并失败');

        return result.fileInfo;
    }

    // ---------------------- 上传状态更新函数 ----------------------
    // 更新进度条（确保显示）
    function updateProgress(fileId, progress) {
        const progressBar = document.getElementById(`progress-${fileId}`);
        if (progressBar) {
            // 强制更新进度条宽度
            progressBar.style.width = `${progress}%`;
            // 更新进度文本
            progressBar.textContent = `${progress}%`;
            // 更新无障碍属性
            progressBar.setAttribute('aria-valuenow', progress);

            // 调试用：确认进度条更新
            console.log(`更新进度: #progress-${fileId} 到 ${progress}%`);
        } else {
            console.error(`未找到进度条元素: #progress-${fileId}`);
        }
    }

    // 更新上传状态
    function updateUploadStatus(fileId, status) {
        const statusElement = document.getElementById(`status-${fileId}`);
        if (statusElement) {
            statusElement.innerHTML = status;
        }
    }

    // 更新上传速度
    function updateUploadSpeed(fileId, speedMB) {
        const speedElement = document.getElementById(`speed-${fileId}`);
        if (speedElement) {
            speedElement.textContent = speedMB > 1
                ? `${speedMB.toFixed(2)} MB/s`
                : `${(speedMB * 1024).toFixed(2)} KB/s`;
        }
    }

    // 标题管理相关
    document.getElementById('save-title').addEventListener('click', function () {
        document.getElementById('title-form').submit();
    });
</script>
</body>

</html>